#include <xen/config.h>
+#include <xen/perfc.h>
#include <xen/spinlock.h>
#include <asm/uaccess.h>
-#ifdef PERF_COUNTERS
-#include <xen/sched.h>
-#include <xen/perfc.h>
-#include <asm/current.h>
-#endif
-
extern struct exception_table_entry __start___ex_table[];
extern struct exception_table_entry __stop___ex_table[];
extern struct exception_table_entry __start___pre_ex_table[];
unsigned long addr = (unsigned long)regs->eip;
unsigned long fixup = search_one_table(
__start___pre_ex_table, __stop___pre_ex_table-1, addr);
- dprintk(XENLOG_INFO, "Pre-exception: %p -> %p\n", _p(addr), _p(fixup));
-#ifdef PERF_COUNTERS
if ( fixup )
+ {
+ dprintk(XENLOG_INFO, "Pre-exception: %p -> %p\n", _p(addr), _p(fixup));
perfc_incrc(exception_fixed);
-#endif
+ }
return fixup;
}
asmlinkage int do_invalid_op(struct cpu_user_regs *regs)
{
- int rc;
+ struct bug_frame bug;
+ struct bug_frame_str bug_str;
+ char *filename, *predicate, *eip = (char *)regs->eip;
+ int rc, id, lineno;
DEBUGGER_trap_entry(TRAP_invalid_op, regs);
- if ( unlikely(!guest_mode(regs)) )
+ if ( likely(guest_mode(regs)) )
{
- struct bug_frame bug;
- if ( is_kernel(regs->eip) &&
- (__copy_from_user(&bug, (char *)regs->eip, sizeof(bug)) == 0) &&
- (memcmp(bug.ud2, "\xf\xb", sizeof(bug.ud2)) == 0) &&
- (memcmp(bug.mov, BUG_MOV_STR, sizeof(bug.mov)) == 0) &&
- (bug.ret == 0xc2) )
- {
- char *filename = (char *)bug.filename;
- unsigned int line = bug.line & 0x7fff;
- int is_bug = !(bug.line & 0x8000);
- printk("Xen %s at %.50s:%d\n",
- is_bug ? "BUG" : "State Dump", filename, line);
- if ( !is_bug )
- {
- show_execution_state(regs);
- regs->eip += sizeof(bug);
- return EXCRET_fault_fixed;
- }
- }
+ if ( (rc = emulate_forced_invalid_op(regs)) != 0 )
+ return rc;
+ return do_guest_trap(TRAP_invalid_op, regs, 0);
+ }
+
+ if ( !is_kernel(eip) ||
+ __copy_from_user(&bug, eip, sizeof(bug)) ||
+ memcmp(bug.ud2, "\xf\xb", sizeof(bug.ud2)) ||
+ (bug.ret != 0xc2) )
+ goto die;
+
+ id = bug.id & 3;
+ if ( id == BUGFRAME_rsvd )
+ goto die;
+
+ if ( id == BUGFRAME_dump )
+ {
+ show_execution_state(regs);
+ regs->eip += sizeof(bug);
+ return EXCRET_fault_fixed;
+ }
+
+ /* BUG() or ASSERT(): decode the filename pointer and line number. */
+ ASSERT((id == BUGFRAME_bug) || (id == BUGFRAME_assert));
+ eip += sizeof(bug);
+ if ( !is_kernel(eip) ||
+ __copy_from_user(&bug_str, eip, sizeof(bug_str)) ||
+ memcmp(bug_str.mov, BUG_MOV_STR, sizeof(bug_str.mov)) )
+ goto die;
+
+ filename = is_kernel(bug_str.str) ? (char *)bug_str.str : "<unknown>";
+ lineno = bug.id >> 2;
+
+ if ( id == BUGFRAME_bug )
+ {
+ printk("Xen BUG at %.50s:%d\n", filename, lineno);
DEBUGGER_trap_fatal(TRAP_invalid_op, regs);
show_execution_state(regs);
- panic("FATAL TRAP: vector = %d (invalid opcode)\n", TRAP_invalid_op);
+ panic("Xen BUG at %.50s:%d\n", filename, lineno);
}
- if ( (rc = emulate_forced_invalid_op(regs)) != 0 )
- return rc;
+ /* ASSERT(): decode the predicate string pointer. */
+ ASSERT(id == BUGFRAME_assert);
+ eip += sizeof(bug_str);
+ if ( !is_kernel(eip) ||
+ __copy_from_user(&bug_str, eip, sizeof(bug_str)) ||
+ memcmp(bug_str.mov, BUG_MOV_STR, sizeof(bug_str.mov)) )
+ goto die;
+
+ predicate = is_kernel(bug_str.str) ? (char *)bug_str.str : "<unknown>";
+ printk("Assertion '%s' failed at %.50s:%d\n",
+ predicate, filename, lineno);
+ DEBUGGER_trap_fatal(TRAP_invalid_op, regs);
+ show_execution_state(regs);
+ panic("Assertion '%s' failed at %.50s:%d\n",
+ predicate, filename, lineno);
- return do_guest_trap(TRAP_invalid_op, regs, 0);
+ die:
+ DEBUGGER_trap_fatal(TRAP_invalid_op, regs);
+ show_execution_state(regs);
+ panic("FATAL TRAP: vector = %d (invalid opcode)\n", TRAP_invalid_op);
+ return 0;
}
asmlinkage int do_int3(struct cpu_user_regs *regs)
#ifndef __X86_32_BUG_H__
#define __X86_32_BUG_H__
-struct bug_frame {
- unsigned char ud2[2];
+struct bug_frame_str {
unsigned char mov[1];
- unsigned long filename;
- unsigned char ret;
- unsigned short line;
+ unsigned long str;
} __attribute__((packed));
-
#define BUG_MOV_STR "\xbc"
-#define __BUG(file, line) \
+#define dump_execution_state() \
+ asm volatile ( \
+ "ud2 ; ret $%c0" \
+ : : "i" (BUGFRAME_dump) )
+
+#define BUG() \
+ asm volatile ( \
+ "ud2 ; ret $%c0 ; .byte 0xbc ; .long %c1" \
+ : : "i" (BUGFRAME_bug | (__LINE__<<2)), \
+ "i" (__FILE__) )
+
+#define assert_failed(p) \
asm volatile ( \
- "ud2 ; .byte 0xbc ; .long %c1 ; ret $%c0" \
- : : "i" (line), "i" (file) )
+ "ud2 ; ret $%c0 ; .byte 0xbc ; .long %c1" \
+ " ; .byte 0xbc ; .long %c2" \
+ : : "i" (BUGFRAME_assert | (__LINE__<<2)), \
+ "i" (__FILE__), "i" (#p) )
#endif /* __X86_32_BUG_H__ */
#ifndef __X86_64_BUG_H__
#define __X86_64_BUG_H__
-struct bug_frame {
- unsigned char ud2[2];
+struct bug_frame_str {
unsigned char mov[2];
- unsigned long filename;
- unsigned char ret;
- unsigned short line;
+ unsigned long str;
} __attribute__((packed));
-
#define BUG_MOV_STR "\x48\xbc"
-#define __BUG(file, line) \
+#define dump_execution_state() \
+ asm volatile ( \
+ "ud2 ; ret $%c0" \
+ : : "i" (BUGFRAME_dump) )
+
+#define BUG() \
+ asm volatile ( \
+ "ud2 ; ret $%c0 ; .byte 0x48,0xbc ; .quad %c1" \
+ : : "i" (BUGFRAME_bug | (__LINE__<<2)), \
+ "i" (__FILE__) )
+
+#define assert_failed(p) \
asm volatile ( \
- "ud2 ; .byte 0x48,0xbc ; .quad %c1 ; ret $%c0" \
- : : "i" (line), "i" (file) )
+ "ud2 ; ret $%c0 ; .byte 0x48,0xbc ; .quad %c1" \
+ " ; .byte 0x48,0xbc ; .quad %c2" \
+ : : "i" (BUGFRAME_assert | (__LINE__<<2)), \
+ "i" (__FILE__), "i" (#p) )
#endif /* __X86_64_BUG_H__ */